

`include "defines.v"

module wb_stage(
  input wire rst,
  input wire [4:0]inst_type_i,
  input wire rd_w_ena_i,
  input wire [4:0]rd_w_addr_i,
  input wire [`REG_BUS]rd_w_data_i,
  input wire [31:0]inst_i,
  input wire [`REG_BUS]pc_i,
  //input wire [`REG_BUS]next_pc_i,
  input wire [11:0]csr_addr_i,
  input wire csr_ena_i,
  input wire [`REG_BUS]csr_op_i,
  input wire [1:0]csr_mode_i,
  input wire putch_en_i,
  input wire [7:0]a0_i,
  input wire ecall_i,
  input wire mret_i,
  input wire mmio_valid_i,

  //input wire time_intr_i,
  input wire time_intr_firstdetect_i,

  //from CSRs
  input wire [`REG_BUS]csr_r_data_i,

  //to CSRs
	output wire csr_w_ena_o,
	output wire [11:0]csr_w_addr_o,
	output reg [`REG_BUS]csr_w_data_o,
	output wire csr_r_ena_o,
	output wire [11:0]csr_r_addr_o,

  //pass
  output wire [4:0]inst_type_o,
  output wire rd_w_ena_o,
  output wire [4:0]rd_w_addr_o,
  output wire [`REG_BUS]rd_w_data_o,
  output wire [31:0]inst_o,
  output wire [`REG_BUS]pc_o,
  //output wire [`REG_BUS]next_pc_o,
  output wire [11:0]csr_addr_o,
  output wire putch_en_o,
  output wire [7:0]a0_o,
  output wire ecall_o,
  output wire mret_o,
  //output wire time_intr_o,
  output wire time_intr_firstdetect_o,
  output wire mmio_valid_o
);

  
assign inst_type_o = inst_type_i;
assign rd_w_ena_o = rd_w_ena_i;
assign rd_w_addr_o = rd_w_addr_i;
assign rd_w_data_o = ((csr_ena_i == 1'b1)? csr_r_data_i : rd_w_data_i);
assign inst_o = inst_i;
assign pc_o = pc_i;
//assign next_pc_o = next_pc_i;
assign csr_addr_o=csr_addr_i;  //for skip in difftest
assign putch_en_o = putch_en_i;
assign a0_o = a0_i;
assign ecall_o= ecall_i;
assign mret_o= mret_i;
//assign time_intr_o = time_intr_i;
assign time_intr_firstdetect_o = time_intr_firstdetect_i;
assign mmio_valid_o = mmio_valid_i;

//csr
assign csr_r_ena_o =  csr_ena_i;
assign csr_r_addr_o =  (csr_ena_i == 1'b1)? csr_addr_i : 0;
assign csr_w_ena_o =  csr_ena_i;
assign csr_w_addr_o =  (csr_ena_i == 1'b1)? csr_addr_i : 0;
//assign csr_w_data_o = (rst == 1'b1)? 0 : csr_op_i;   //csrrs?
always @(*) begin
  if (csr_ena_i == 1'b0) begin
    csr_w_data_o = `ZERO_WORD;
  end
  else begin
    if (csr_mode_i == 2'b00) begin       //W
      csr_w_data_o = csr_op_i;   
    end
    else if (csr_mode_i == 2'b01) begin     //C
      csr_w_data_o = ~csr_op_i & csr_r_data_i;
    end
    else if (csr_mode_i == 2'b10) begin     //S
      csr_w_data_o = csr_op_i | csr_r_data_i;
    end
    else begin
      csr_w_data_o = `ZERO_WORD;
    end
  end
end



endmodule
